using System;
using Urs.Data.Domain.Stores;
using Urs.Data.Domain.Users;
using Urs.Data.Domain.Orders;
using Urs.Data.Domain.Configuration;

namespace Urs.Services.Stores
{
    public partial class PriceCalculationService : IPriceCalculationService
    {
        #region Fields

        private readonly ICategoryService _categoryService;
        private readonly IGoodsSpecParser _goodsSpecParser;
        private readonly ShoppingCartSettings _shoppingCartSettings;

        #endregion

        #region Ctor

        public PriceCalculationService(ICategoryService categoryService,
            IGoodsSpecParser goodsSpecParser, ShoppingCartSettings shoppingCartSettings)
        {
            this._categoryService = categoryService;
            this._goodsSpecParser = goodsSpecParser;
            this._shoppingCartSettings = shoppingCartSettings;
        }

        #endregion


        #region Methods

        public virtual decimal? GetSpecialPrice(Goods goods)
        {
            if (goods == null)
                throw new ArgumentNullException("goods");

            if (!goods.SpecialPrice.HasValue)
                return null;

            DateTime now = DateTime.Now;
            if (goods.SpecialStartTime.HasValue)
            {
                DateTime startDate = DateTime.SpecifyKind(goods.SpecialStartTime.Value, DateTimeKind.Utc);
                if (startDate.CompareTo(now) > 0)
                    return null;
            }
            if (goods.SpecialEndTime.HasValue)
            {
                DateTime endDate = DateTime.SpecifyKind(goods.SpecialEndTime.Value, DateTimeKind.Utc);
                if (endDate.CompareTo(now) < 0)
                    return null;
            }

            return goods.SpecialPrice.Value;
        }

        public virtual decimal GetFinalPrice(Goods goods)
        {
            return GetFinalPrice(goods, null, decimal.Zero, 1);
        }

        public virtual decimal GetFinalPrice(Goods goods, User user, decimal attributesPrice, int quantity)
        {
            decimal result = goods.Price;

            var specialPrice = GetSpecialPrice(goods);
            if (specialPrice.HasValue)
                result = specialPrice.Value;

            if (attributesPrice > 0)
                result = attributesPrice;

            if (result < decimal.Zero)
                result = decimal.Zero;
            return result;
        }

        public virtual decimal GetSubTotal(ShoppingCartItem shoppingCartItem)
        {
            return GetUnitPrice(shoppingCartItem) * shoppingCartItem.Quantity;
        }

        public virtual decimal GetUnitPrice(ShoppingCartItem shoppingCartItem)
        {
            decimal finalPrice = decimal.Zero;
            var goods = shoppingCartItem.Goods;
            if (goods != null)
            {
                decimal attributesTotalPrice = decimal.Zero;
                var combination = _goodsSpecParser.FindGoodsSpecCombination(goods, shoppingCartItem.AttributesXml);
                if (combination != null)
                    attributesTotalPrice = combination.Price;

                finalPrice = GetFinalPrice(goods, shoppingCartItem.User, attributesTotalPrice, shoppingCartItem.Quantity);
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
                finalPrice = Math.Round(finalPrice, 2);

            return finalPrice;
        }
        #endregion
    }
}
